home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / xfonts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  9.2 KB  |  331 lines

  1. /* $Id: xfonts.c,v 1.7 1997/03/13 03:14:34 brianp Exp $ */
  2.  
  3. /* xfonts.c -- glXUseXFont() for Mesa
  4.    Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21.  
  22. /*
  23.  * $Log: xfonts.c,v $
  24.  * Revision 1.7  1997/03/13 03:14:34  brianp
  25.  * removed unused variable 'c' from dump_font_struct()
  26.  *
  27.  * Revision 1.6  1996/11/20 03:05:14  brianp
  28.  * added #include "GL/glx.h"
  29.  *
  30.  * Revision 1.5  1996/10/22 01:02:46  brianp
  31.  * call XFreeFontInfo instead of XFreeFont (again)
  32.  *
  33.  * Revision 1.4  1996/10/09 03:07:42  brianp
  34.  * replaced XFreeFontInfo with XFreeFont
  35.  *
  36.  * Revision 1.3  1996/09/19 03:41:48  brianp
  37.  * updated for new X/Mesa changes
  38.  *
  39.  * Revision 1.2  1996/09/15 01:50:05  brianp
  40.  * fixed #includes
  41.  *
  42.  * Revision 1.1  1996/09/13 01:38:16  brianp
  43.  * Initial revision
  44.  *
  45.  */
  46.  
  47.  
  48.  
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <X11/Xlib.h>
  53. #include <X11/Xutil.h>
  54. #include "GL/gl.h"
  55. #include "GL/glx.h"
  56. #include "GL/xmesa.h"
  57. #include "macros.h"
  58.  
  59.  
  60. /* Some debugging info.  */
  61.  
  62. #ifdef DEBUG
  63. #include <ctype.h>
  64.  
  65. int debug_xfonts = 0;
  66.  
  67. static void
  68. dump_char_struct (XCharStruct *ch, char *prefix)
  69. {
  70.   printf ("%slbearing = %d, rbearing = %d, width = %d\n",
  71.       prefix, ch->lbearing, ch->rbearing, ch->width);
  72.   printf ("%sascent = %d, descent = %d, attributes = %u\n",
  73.       prefix, ch->ascent, ch->descent, ch->attributes);
  74. }
  75.  
  76. static void
  77. dump_font_struct (XFontStruct *font)
  78. {
  79.   printf ("ascent = %d, descent = %d\n", font->ascent, font->descent);
  80.   printf ("char_or_byte2 = (%d,%d)\n",
  81.       font->min_char_or_byte2, font->max_char_or_byte2);
  82.   printf ("byte1 = (%d,%d)\n", font->min_byte1, font->max_byte1);
  83.   printf ("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
  84.   printf ("default_char = %c (\\%03o)\n",
  85.       isprint (font->default_char) ? font->default_char : ' ',
  86.       font->default_char);
  87.   dump_char_struct (&font->min_bounds, "min> ");
  88.   dump_char_struct (&font->max_bounds, "max> ");
  89. #if 0
  90.   for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++)
  91.     {
  92.       char prefix[8];
  93.       sprintf (prefix, "%d> ", c);
  94.       dump_char_struct (&font->per_char[c], prefix);
  95.     }
  96. #endif
  97. }
  98.  
  99. static void
  100. dump_bitmap (unsigned int width, unsigned int height, GLubyte *bitmap)
  101. {
  102.   int x, y;
  103.  
  104.   printf ("    ");
  105.   for (x = 0; x < 8*width; x++)
  106.     printf ("%o", 7 - (x % 8));
  107.   putchar ('\n');
  108.   for (y = 0; y < height; y++)
  109.     {
  110.       printf ("%3o:", y);
  111.       for (x = 0; x < 8*width; x++)
  112.         putchar ((bitmap[width*(height - y - 1) + x/8] & (1 << (7 - (x % 8))))
  113.          ? '*' : '.');
  114.       printf ("   ");
  115.       for (x = 0; x < width; x++)
  116.     printf ("0x%02x, ", bitmap[width*(height - y - 1) + x]);
  117.       putchar ('\n');
  118.     }
  119. }
  120. #endif /* DEBUG */
  121.  
  122.  
  123. /* Implementation.  */
  124.  
  125. /* Fill a BITMAP with a character C from thew current font
  126.    in the graphics context GC.  WIDTH is the width in bytes
  127.    and HEIGHT is the height in bits.
  128.  
  129.    Note that the generated bitmaps must be used with
  130.  
  131.     glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
  132.     glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
  133.     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
  134.     glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
  135.     glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
  136.     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  137.  
  138.    Possible optimizations:
  139.  
  140.      * use only one reusable pixmap with the maximum dimensions.
  141.      * draw the entire font into a single pixmap (careful with
  142.        proportional fonts!).
  143. */
  144.  
  145. static void
  146. fill_bitmap (Display *dpy, Window win, GC gc,
  147.          unsigned int width, unsigned int height,
  148.          int x0, int y0, char c, GLubyte *bitmap)
  149. {
  150.   XImage *image;
  151.   int x, y;
  152.   Pixmap pixmap;
  153.  
  154.   pixmap = XCreatePixmap (dpy, win, 8*width, height, 1);
  155.   XSetForeground(dpy, gc, 0);
  156.   XFillRectangle (dpy, pixmap, gc, 0, 0, 8*width, height);
  157.   XSetForeground(dpy, gc, 1);
  158.   XDrawString (dpy, pixmap, gc, x0, y0, &c, 1);
  159.  
  160.   image = XGetImage (dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap);
  161.  
  162.   /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */
  163.   for (y = 0; y < height; y++)
  164.     for (x = 0; x < 8*width; x++)
  165.       if (XGetPixel (image, x, y))
  166.     bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8)));
  167.   
  168.   XFreePixmap (dpy, pixmap);
  169.   XDestroyImage (image);
  170. }
  171.  
  172. #include "xmesaP.h"
  173. #include "context.h"
  174.  
  175. void
  176. glXUseXFont (Font font, int first, int count, int listbase)
  177. {
  178.   XMesaContext CC;
  179.   Display *dpy;
  180.   Window win;
  181.   Pixmap pixmap;
  182.   GC gc;
  183.   XGCValues values;
  184.   unsigned long valuemask;
  185.  
  186.   XFontStruct *fs;
  187.  
  188.   GLint swapbytes, lsbfirst, rowlength;
  189.   GLint skiprows, skippixels, alignment;
  190.  
  191.   unsigned int max_width, max_height, max_bm_width, max_bm_height;
  192.   GLubyte *bm;
  193.  
  194.   int i;
  195.  
  196.   CC = XMesaGetCurrentContext();  
  197.   dpy = CC->display;
  198.   win = CC->xm_buffer->frontbuffer;
  199.  
  200.   fs = XQueryFont (dpy, font);  
  201.   if (!fs)
  202.     {
  203.       gl_error (CC->gl_ctx, GL_INVALID_VALUE,
  204.         "Couldn't get font structure information");
  205.       return;
  206.     }
  207.  
  208.   /* Allocate a bitmap that can fit all characters.  */
  209.   max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
  210.   max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
  211.   max_bm_width = (max_width + 7) / 8;
  212.   max_bm_height = max_height;
  213.  
  214.   bm = (GLubyte *) malloc ((max_bm_width * max_bm_height) * sizeof (GLubyte));
  215.   if (!bm)
  216.     {
  217.       gl_error (CC->gl_ctx, GL_OUT_OF_MEMORY,
  218.         "Couldn't allocate bitmap in glXUseXFont()");
  219.       return;
  220.     }
  221.  
  222.   /* Save the current packing mode for bitmaps.  */
  223.   glGetIntegerv    (GL_UNPACK_SWAP_BYTES, &swapbytes);
  224.   glGetIntegerv    (GL_UNPACK_LSB_FIRST, &lsbfirst);
  225.   glGetIntegerv    (GL_UNPACK_ROW_LENGTH, &rowlength);
  226.   glGetIntegerv    (GL_UNPACK_SKIP_ROWS, &skiprows);
  227.   glGetIntegerv    (GL_UNPACK_SKIP_PIXELS, &skippixels);
  228.   glGetIntegerv    (GL_UNPACK_ALIGNMENT, &alignment);
  229.  
  230.   /* Enforce a standard packing mode which is compatible with
  231.      fill_bitmap() from above.  This is actually the default mode,
  232.      except for the (non)alignment.  */
  233.   glPixelStorei    (GL_UNPACK_SWAP_BYTES, GL_FALSE);
  234.   glPixelStorei    (GL_UNPACK_LSB_FIRST, GL_FALSE);
  235.   glPixelStorei    (GL_UNPACK_ROW_LENGTH, 0);
  236.   glPixelStorei    (GL_UNPACK_SKIP_ROWS, 0);
  237.   glPixelStorei    (GL_UNPACK_SKIP_PIXELS, 0);
  238.   glPixelStorei    (GL_UNPACK_ALIGNMENT, 1);
  239.  
  240.   pixmap = XCreatePixmap (dpy, win, 10, 10, 1);
  241.   values.foreground = BlackPixel (dpy, DefaultScreen (dpy));
  242.   values.background = WhitePixel (dpy, DefaultScreen (dpy));
  243.   values.font = fs->fid;
  244.   valuemask = GCForeground | GCBackground | GCFont;
  245.   gc = XCreateGC (dpy, pixmap, valuemask, &values);
  246.   XFreePixmap (dpy, pixmap);
  247.  
  248. #ifdef DEBUG
  249.   if (debug_xfonts)
  250.     dump_font_struct (fs);
  251. #endif
  252.   
  253.   for (i = 0; i < count; i++)
  254.     {
  255.       unsigned int width, height, bm_width, bm_height;
  256.       GLfloat x0, y0, dx, dy;
  257.       XCharStruct *ch;
  258.       int x, y;
  259.       int c = first + i;
  260.       int list = listbase + i;
  261.  
  262.       if (fs->per_char
  263.       && (c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2))
  264.     ch = &fs->per_char[c-fs->min_char_or_byte2];
  265.       else
  266.     ch = &fs->max_bounds;
  267.  
  268. #ifdef DEBUG
  269.       if (debug_xfonts)
  270.     {
  271.       char s[7];
  272.       sprintf (s, isprint (c) ? "%c> " : "\\%03o> ", c);
  273.       dump_char_struct (ch, s);
  274.     }
  275. #endif
  276.       
  277.       /* glBitmap()' parameters:
  278.      straight from the glXUseXFont(3) manpage.  */
  279.       width = ch->rbearing - ch->lbearing;
  280.       height = ch->ascent + ch->descent;
  281.       x0 = - ch->lbearing;
  282.       y0 = ch->descent - 1;
  283.       dx = ch->width;
  284.       dy = 0;
  285.  
  286.       /* X11's starting point.  */
  287.       x = - ch->lbearing;
  288.       y = ch->ascent;
  289.       
  290.       /* Round the width to a multiple of eight.  We will use this also
  291.      for the pixmap for capturing the X11 font.  This is slightly
  292.      inefficient, but it makes the OpenGL part real easy.  */
  293.       bm_width = (width + 7) / 8;
  294.       bm_height = height;
  295.  
  296.       glNewList (list, GL_COMPILE);
  297.         if ((c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2)
  298.         && (bm_width > 0) && (bm_height > 0))
  299.       {
  300.         MEMSET (bm, '\0', bm_width * bm_height);
  301.         fill_bitmap (dpy, win, gc, bm_width, bm_height, x, y, c, bm);
  302.         glBitmap (width, height, x0, y0, dx, dy, bm);
  303. #ifdef DEBUG
  304.         if (debug_xfonts)
  305.           {
  306.         printf ("width/height = %d/%d\n", width, height);
  307.         printf ("bm_width/bm_height = %d/%d\n", bm_width, bm_height);
  308.         dump_bitmap (bm_width, bm_height, bm);
  309.           }
  310. #endif
  311.       }
  312.     else
  313.       glBitmap (0, 0, 0.0, 0.0, dx, dy, NULL);
  314.       glEndList ();
  315.     }
  316.  
  317.   free (bm);
  318.   XFreeFontInfo( NULL, fs, 0 );
  319.   XFreeGC (dpy, gc);
  320.  
  321.   /* Restore saved packing modes.  */    
  322.   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
  323.   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
  324.   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
  325.   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
  326.   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
  327.   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
  328. }
  329.  
  330. /* The End. */
  331.